﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Shop.Model;
using System.Data.Linq;
using System.Web;
using Shop.Framework.Keys;
using System.Web.Caching;

namespace Shop.Framework.Services {
    public class ProductService:BaseService {

        private object _Padlock = new object();
        public List<Product> FindProducts(int idCategory) {

            
            List<Product> productList = null;
            productList = HttpRuntime.Cache.Get(string.Format("{0}-{1}", ConstantKeys.Category, idCategory)) as List<Product>;

            if (productList == null) {
                ShopDatabaseDataContext context = Context;

                //Prefetch items
                DataLoadOptions option = new DataLoadOptions();
                option.LoadWith<Product>(prd => prd.ProductImages);
                context.LoadOptions = option;
                if (idCategory != 0) {
                    var res = from a in context.Products
                              join b in context.ProductCategories on a.IdProduct equals b.IdProduct
                              where b.IdCategory == idCategory
                              select a;

                    productList = res.ToList();
                } else {
                    productList = context.Products.ToList();
                }

                HttpRuntime.Cache.Add(
                    string.Format("{0}-{1}", ConstantKeys.Category, idCategory),
                    productList,
                    null,
                    DateTime.Now.AddHours(2),
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Normal,
                    null);
            }
            return productList;
        }

        public Product FindProduct(int idProduct) {
            ShopDatabaseDataContext context = Context;
            DataLoadOptions option = new DataLoadOptions();
            
            option.LoadWith<Product>(prd => prd.ProductImages);
            context.LoadOptions = option;
            //context.Products.Where(prd => prd.IdProduct == idProduct).FirstOrDefault();

            var p = from i in context.Products
                    where i.IdProduct == idProduct
                    select i;

            return p.FirstOrDefault();
        }

        public List<Product> FindProductsByDesigner(int idDesigner) {


            List<Product> productList = null;
            //productList = HttpRuntime.Cache.Get(string.Format("{0}-{1}", ConstantKeys.Designer, idDesigner)) as List<Product>;

            if (productList == null) {
                ShopDatabaseDataContext context = Context;
                DataLoadOptions option = new DataLoadOptions();
                option.LoadWith<Product>(prd => prd.ProductImages);
                context.LoadOptions = option;
                if (idDesigner != 0) {
                    var res = from a in context.Products                              
                              where a.IdDesigner == idDesigner
                              select a;

                    productList = res.ToList();
                } else {
                    productList = context.Products.ToList();
                }

                HttpRuntime.Cache.Add(
                    string.Format("{0}-{1}", ConstantKeys.Designer, idDesigner),
                    productList,
                    null,
                    DateTime.Now.AddHours(2),
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Normal,
                    null);
            }
            return productList;
        }

        public int GetInstock(int idProduct) {
            ShopDatabaseDataContext context = Context;
            var res = from i in context.Skus
                      where i.IdProduct == idProduct
                          select i;

            var skus = res.ToList();
            int total = 0;
            skus.ForEach(delegate(Sku sku) {
                total += sku.Quantity;
            });

            return total;

        }


        public OrderItem CreateCartItem(int idProduct, int quantity) {
            Product product = FindProduct(idProduct);
            if (product == null)
                return null;

            OrderItem item = new OrderItem {
                IdProduct = idProduct,
                Name = product.Name,
                Product = product,
                Quantity = quantity,
                TaxedPrice = product.TaxedPrice
            };

            return item;
        }

        public void SaveModified(Product p, int idCategory) {
            try {
                
                ShopDatabaseDataContext context = Context;
                Product pd = context.Products.FirstOrDefault(prd => prd.IdProduct == p.IdProduct);

                pd.IdDesigner = p.IdDesigner;
                pd.Name = p.Name;
                pd.Description = p.Description;
                pd.DateEncoded = p.DateEncoded;
                pd.Tags = p.Tags;
                pd.Keywords = p.Keywords;
                pd.Title = p.Title;
                pd.IsDeleted = p.IsDeleted;
                pd.IsViewable = p.IsViewable;
                pd.Price = p.Price;
                pd.TaxedPrice = p.TaxedPrice;
                
                context.SubmitChanges();
                var prodList = HttpRuntime.Cache[string.Format("{0}-{1}", ConstantKeys.Category, idCategory)] as List<Product>;
                int index = prodList.FindIndex( found => found.IdProduct == pd.IdProduct);
                prodList[index] = pd;

            } catch (Exception ex) {
                throw new Exception("Error on saving product..", ex);
            }
        }

        public void SaveNewProduct(Product p, int idCategory) {
            try {
                 ShopDatabaseDataContext context = Context;
                 context.Products.InsertOnSubmit(p);
                 p.ProductCategories.Add(new ProductCategory{IdCategory = idCategory, Product = p});                 
                 context.SubmitChanges();

                 List<Product> productList = HttpRuntime.Cache[string.Format("{0}-{1}", ConstantKeys.Category, idCategory)] as List<Product>;
                 productList.Add(p);

                 HttpRuntime.Cache.Add(
                     string.Format("{0}-{1}", ConstantKeys.Category, idCategory),
                     productList,
                     null,
                     DateTime.Now.AddHours(2),
                     Cache.NoSlidingExpiration,
                     CacheItemPriority.Normal,
                     null);


            } catch (Exception ex) {
                throw new Exception("Error on creation new product..", ex);
            }
        }

        public void AddImageToProduct(int idProduct, string filename) {
            try {
                ShopDatabaseDataContext context = Context;
                ProductImage image = new ProductImage {
                    IdProduct = idProduct,
                    IsDefault = true,
                    Name = filename
                };

                context.ProductImages.InsertOnSubmit(image);
                context.SubmitChanges();
            } catch (Exception ex) {
                throw new Exception("An error occured while saving the image..", ex);
            }
        }

        public void DeleteImage(int idProductImage, int idProduct) {

            try {
                ShopDatabaseDataContext context = Context;
                var imgList = from i in context.ProductImages
                              where i.IdProduct == idProduct
                              select i;


                var toBeDeleted = from i in imgList
                                  where i.IdProductImage == idProductImage
                                  select i;

                context.ProductImages.DeleteOnSubmit(toBeDeleted.FirstOrDefault());

                if (toBeDeleted.FirstOrDefault().IsDefault) {
                    var p = imgList.FirstOrDefault(x => x.IdProductImage != idProductImage);
                    if (p != null)
                        p.IsDefault = true;
                }

                context.SubmitChanges();

            } catch (Exception ex) {
                throw new Exception("Image deletion error.", ex);
            }

        }

        public void SetAsDefaultImage(int idProduct, int idProductImage) {
            try {
                ShopDatabaseDataContext context = Context;
                var imgList = from i in context.ProductImages
                              where i.IdProduct == idProduct
                              select i;

                foreach (var t in imgList) {
                    if (t.IdProductImage == idProductImage)
                        t.IsDefault = true;

                    else
                        t.IsDefault = false;
                }

                context.SubmitChanges();
            } catch (Exception ex) {
                throw new Exception("Image operation failed..", ex);
            }
        }

        public void RefreshImage(Product product) {

            try {
                ShopDatabaseDataContext context = Context;
                var images = from i in context.ProductImages
                             where i.IdProduct == product.IdProduct
                             select i;

                product.ProductImages.Clear();
                product.ProductImages.AddRange(images.ToList());

            } catch (Exception ex) {
                throw new Exception("Image operation failed..", ex);
            }
            
        }
    }
}
